﻿import numpy as np
 
a = np.array([0,30,45,60,90])
print ('不同角度的正弦值：')
# 通过乘 pi/180 转化为弧度  
print (np.sin(a*np.pi/180))
print ('\n')
print ('数组中角度的余弦值：')
print (np.cos(a*np.pi/180))
print ('\n')
print ('数组中角度的正切值：')
print (np.tan(a*np.pi/180))




a = np.array([0,30,45,60,90])  
print ('含有正弦值的数组：')
sin = np.sin(a*np.pi/180)  
print (sin)
print ('\n')
print ('计算角度的反正弦，返回值以弧度为单位：')
inv = np.arcsin(sin)  
print (inv)
print ('\n')
print ('通过转化为角度制来检查结果：')
print (np.degrees(inv))
print ('\n')
print ('arccos 和 arctan 函数行为类似：')
cos = np.cos(a*np.pi/180)  
print (cos)
print ('\n')
print ('反余弦：')
inv = np.arccos(cos)  
print (inv)
print ('\n')
print ('角度制单位：')
print (np.degrees(inv))
print ('\n')
print ('tan 函数：')
tan = np.tan(a*np.pi/180)  
print (tan)
print ('\n')
print ('反正切：')
inv = np.arctan(tan)  
print (inv)
print ('\n')
print ('角度制单位：')
print (np.degrees(inv))


a = np.array([1.0,5.55,  123,  0.567,  25.532])  
print  ('原数组：')
print (a)
print ('\n')
print ('舍入后：')
print (np.around(a))
print (np.around(a, decimals =  1))
print (np.around(a, decimals =  -1))

#返回小于或者等于指定表达式的最大整数，即向下取整
a = np.array([-1.7,  1.5,  -0.2,  0.6,  10])
print ('提供的数组：')
print (a)
print ('\n')
print ('修改后的数组：')
print (np.floor(a))

#返回大于或者等于指定表达式的最小整数，即向上取整
a = np.array([-1.7,  1.5,  -0.2,  0.6,  10])  
print  ('提供的数组：')
print (a)
print ('\n')
print ('修改后的数组：')
print (np.ceil(a))


#基本数学运算
# 创建示例数组
arr = np.array([1, 2, 3, 4, 5])
arr2 = np.array([6, 7, 8, 9, 10])

# 基本算术运算
print("加法:", np.add(arr, arr2))        # [ 7  9 11 13 15]
print("减法:", np.subtract(arr2, arr))   # [5 5 5 5 5]
print("乘法:", np.multiply(arr, arr2))   # [ 6 14 24 36 50]
print("除法:", np.divide(arr2, arr))     # [6.  3.5 2.666... 2.25 2.]
print("幂运算:", np.power(arr, 2))       # [ 1  4  9 16 25]
print("取余:", np.mod(arr2, arr))        # [0 1 2 1 0]

# 绝对值
arr_neg = np.array([-1, -2, 3, -4])
print("绝对值:", np.abs(arr_neg))        # [1 2 3 4]




#三角函数
# 三角函数
angles = np.array([0, 30, 45, 60, 90]) * np.pi / 180  # 转换为弧度

print("正弦值:", np.sin(angles))
print("余弦值:", np.cos(angles))
print("正切值:", np.tan(angles))

# 反三角函数
print("反正弦:", np.arcsin([0, 0.5, 1]))  # 返回弧度值
print("反余弦:", np.arccos([0, 0.5, 1]))
print("反正切:", np.arctan([0, 0.5, 1]))

# 角度和弧度转换
print("弧度转角度:", np.degrees(np.pi/2))  # 90.0
print("角度转弧度:", np.radians(180))      # π





#指数和对数函数
# 指数函数
arr = np.array([1, 2, 3])
print("e的幂次:", np.exp(arr))           # [e^1, e^2, e^3]
print("2的幂次:", np.exp2(arr))          # [2, 4, 8]
print("10的幂次:", np.power(10, arr))    # [10, 100, 1000]

# 对数函数
arr = np.array([1, 10, 100])
print("自然对数:", np.log(arr))          # [0, 2.302, 4.605]
print("以2为底的对数:", np.log2(arr))     # [0, 3.321, 6.643]
print("以10为底的对数:", np.log10(arr))   # [0, 1, 2]




# 双曲函数
x = np.array([0, 0.5, 1])
print("双曲正弦:", np.sinh(x))
print("双曲余弦:", np.cosh(x))
print("双曲正切:", np.tanh(x))

# 反双曲函数
print("反双曲正弦:", np.arcsinh(x))
print("反双曲余弦:", np.arccosh([1, 2, 3]))  # 输入必须≥1
print("反双曲正切:", np.arctanh([0, 0.5]))   # 输入必须在(-1, 1)范围内






# 创建示例数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 基本统计
print("平均值:", np.mean(arr))
print("中位数:", np.median(arr))
print("标准差:", np.std(arr))
print("方差:", np.var(arr))
print("最小值:", np.min(arr))
print("最大值:", np.max(arr))

# 沿特定轴计算
print("每列平均值:", np.mean(arr, axis=0))  # [4. 5. 6.]
print("每行平均值:", np.mean(arr, axis=1))  # [2. 5. 8.]

# 百分位数
print("25%分位数:", np.percentile(arr, 25))
print("75%分位数:", np.percentile(arr, 75))

# 相关性和协方差
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([5, 4, 3, 2, 1])
print("相关系数:", np.corrcoef(arr1, arr2))
print("协方差:", np.cov(arr1, arr2))




# 舍入函数
arr = np.array([1.234, 2.567, 3.899])

print("四舍五入:", np.round(arr, 2))      # [1.23 2.57 3.90]
print("向下取整:", np.floor(arr))         # [1. 2. 3.]
print("向上取整:", np.ceil(arr))          # [2. 3. 4.]
print("截断小数:", np.trunc(arr))         # [1. 2. 3.]



# 比较函数
arr1 = np.array([1, 2, 3])
arr2 = np.array([3, 2, 1])

print("大于比较:", np.greater(arr1, arr2))    # [False False True]
print("大于等于:", np.greater_equal(arr1, arr2))
print("小于比较:", np.less(arr1, arr2))        # [True False False]
print("小于等于:", np.less_equal(arr1, arr2))
print("等于:", np.equal(arr1, arr2))          # [False True False]
print("不等于:", np.not_equal(arr1, arr2))     # [True False True]

# 逻辑函数
arr_bool = np.array([True, False, True])
print("逻辑与:", np.logical_and(arr_bool, [True, True, False]))  # [True False False]
print("逻辑或:", np.logical_or(arr_bool, [True, False, False]))  # [True False True]
print("逻辑非:", np.logical_not(arr_bool))                       # [False True False]





# 线性代数函数
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

print("矩阵乘法:", np.dot(A, B))           # [[19 22] [43 50]]
print("点积:", np.vdot(A, B))              # 1 * 5 + 2 * 6 + 3 * 7 + 4 * 8 = 70
print("内积:", np.inner(A, B))             # [[17 23] [39 53]]
print("外积:", np.outer(A, B))             # 4x4矩阵

# 行列式和逆矩阵
print("行列式:", np.linalg.det(A))         # -2.0
print("逆矩阵:", np.linalg.inv(A))         # [[-2.0 1.0] [1.5 -0.5]]

# 特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
print("特征值:", eigenvalues)              # [-0.372 5.372]
print("特征向量:", eigenvectors)

# 矩阵的迹和范数
print("迹:", np.trace(A))                  # 5
print("范数:", np.linalg.norm(A))          # 5.477...



# 多项式函数
# 多项式系数: x^2 + 2x + 3
p = np.poly1d([1, 2, 3])

print("多项式:", p)
print("在x=2处的值:", p(2))                # 11
print("多项式的根:", p.r)                  # [-1±j√2]
print("多项式的导数:", p.deriv())           # 2x + 2
print("多项式的不定积分:", p.integ())       # (1/3)x^3 + x^2 + 3x

# 多项式拟合
x = np.array([0, 1, 2, 3, 4])
y = np.array([1, 3, 5, 7, 9])
coefficients = np.polyfit(x, y, 1)        # 一次多项式拟合
print("拟合系数:", coefficients)           # [2. 1.] -> y = 2x + 1





# 离散傅里叶变换
x = np.array([1, 2, 3, 4])
print("FFT:", np.fft.fft(x))              # 快速傅里叶变换
print("IFFT:", np.fft.ifft(x))            # 逆傅里叶变换

# 频率和采样
freqs = np.fft.fftfreq(4, d=0.1)          # 4个样本，采样间隔0.1秒
print("频率:", freqs)




# 窗口函数（用于信号处理）
print("汉宁窗:", np.hanning(5))           # [0.  0.5 1.  0.5 0.]
print("汉明窗:", np.hamming(5))           # [0.08 0.54 1.  0.54 0.08]
print("布莱克曼窗:", np.blackman(5))       # [-1.387e-17 3.400e-01 1.000e+00 3.400e-01 -1.387e-17]





# 数值积分
def f(x):
    return x**2

# 梯形法积分
x = np.linspace(0, 2, 100)
y = f(x)
integral = np.trapz(y, x)
print("积分值:", integral)                 # 约等于 8/3 ≈ 2.666...

# 数值微分
dx = x[1] - x[0]
derivative = np.gradient(y, dx)
print("在x=1处的导数值:", derivative[50])  # 约等于 2.0





# 设置随机种子以确保结果可重现
np.random.seed(42)

# 各种分布随机数
print("均匀分布:", np.random.rand(5))                 # [0,1)均匀分布
print("标准正态分布:", np.random.randn(5))            # 标准正态分布
print("整数随机数:", np.random.randint(0, 10, 5))     # [0,10)整数
print("正态分布:", np.random.normal(0, 1, 5))         # 正态分布，均值0，标准差1
print("泊松分布:", np.random.poisson(5, 5))           # 泊松分布，λ=5

# 随机排列和抽样
arr = np.array([1, 2, 3, 4, 5])
print("随机排列:", np.random.permutation(arr))        # 随机排列
print("随机抽样:", np.random.choice(arr, 3))          # 随机抽取3个元素



# 集合操作
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([3, 4, 5, 6, 7])

print("并集:", np.union1d(arr1, arr2))        # [1 2 3 4 5 6 7]
print("交集:", np.intersect1d(arr1, arr2))     # [3 4 5]
print("差集:", np.setdiff1d(arr1, arr2))       # [1 2]
print("对称差:", np.setxor1d(arr1, arr2))      # [1 2 6 7]



# 创建示例数组
arr = np.array([3, 1, 4, 2, 5])
print("原始数组:", arr)

# 1. 使用sort()方法（原地排序）
arr.sort()
print("sort()排序后:", arr)

# 2. 使用np.sort()函数（返回新数组）
arr = np.array([3, 1, 4, 2, 5])
sorted_arr = np.sort(arr)
print("np.sort()排序后:", sorted_arr)
print("原数组保持不变:", arr)

# 3. 获取排序索引
arr = np.array([3, 1, 4, 2, 5])
indices = np.argsort(arr)
print("排序索引:", indices)
print("通过索引获取排序结果:", arr[indices])




# 二维数组排序
arr_2d = np.array([[3, 1, 4], [2, 5, 0], [7, 6, 8]])
print("原始二维数组:")
print(arr_2d)

# 按行排序
print("按行排序:")
print(np.sort(arr_2d, axis=1))

# 按列排序
print("按列排序:")
print(np.sort(arr_2d, axis=0))

# 获取排序索引
print("按行排序的索引:")
print(np.argsort(arr_2d, axis=1))





# 使用lexsort进行多键排序
first_names = np.array(['Alice', 'Bob', 'Charlie', 'David'])
last_names = np.array(['Smith', 'Jones', 'Smith', 'Jones'])
ages = np.array([25, 30, 22, 35])

# 先按姓氏排序，再按名字排序
indices = np.lexsort((first_names, last_names))
print("按姓氏和名字排序:")
print("姓氏:", last_names[indices])
print("名字:", first_names[indices])
print("年龄:", ages[indices])

# 使用partition进行部分排序
arr = np.array([3, 1, 4, 2, 5, 0, 6])
# 将数组分为两部分：前3个最小的元素和其他元素
partitioned = np.partition(arr, 3)
print("部分排序 (前3个最小):", partitioned)

# 获取第k小的元素
k = 3
kth_smallest = np.partition(arr, k)[k]
print(f"第{k}小的元素:", kth_smallest)






# 创建示例数组
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

# 基本布尔索引
mask = arr > 5
print("大于5的元素:", arr[mask])

# 多条件筛选
mask = (arr > 3) & (arr < 8)
print("大于3且小于8的元素:", arr[mask])

# 使用OR条件
mask = (arr < 3) | (arr > 7)
print("小于3或大于7的元素:", arr[mask])

# 使用NOT条件
mask = ~(arr > 5)
print("不大于5的元素:", arr[mask])




# 基本用法
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
indices = np.where(arr > 5)
print("大于5的元素的索引:", indices)
print("大于5的元素:", arr[indices])

# 替换满足条件的值
result = np.where(arr > 5, arr, -1)
print("替换结果:", result)

# 多条件替换
result = np.where(arr < 3, 0, np.where(arr > 7, 10, arr))
print("多条件替换结果:", result)




# 提取满足条件的元素
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
condition = arr % 2 == 0  # 偶数
extracted = np.extract(condition, arr)
print("偶数元素:", extracted)




# 获取非零元素的索引
arr = np.array([0, 1, 0, 3, 0, 5])
nonzero_indices = np.nonzero(arr)
print("非零元素的索引:", nonzero_indices)
print("非零元素:", arr[nonzero_indices])



# 多条件选择
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

# 定义条件列表
conditions = [
    arr < 3,
    (arr >= 3) & (arr < 7),
    arr >= 7
]

# 定义对应条件的值
choices = [10, 20, 30]

# 应用选择
result = np.select(conditions, choices)
print("多条件选择结果:", result)





# 创建结构化数组
dtype = [('name', 'U10'), ('age', 'i4'), ('score', 'f4')]
students = np.array([
    ('Alice', 25, 88.5),
    ('Bob', 22, 92.0),
    ('Charlie', 23, 78.5),
    ('David', 24, 95.0)
], dtype=dtype)

print("原始学生数据:")
print(students)

# 按分数降序排序
sorted_by_score = np.sort(students, order='score')[::-1]
print("按分数降序排序:")
print(sorted_by_score)

# 筛选分数高于85的学生
high_scorers = students[students['score'] > 85]
print("分数高于85的学生:")
print(high_scorers)

# 按年龄排序高分数学生
high_scorers_sorted = np.sort(high_scorers, order='age')
print("高分数学生按年龄排序:")
print(high_scorers_sorted)



# 使用布尔索引而不是循环
arr = np.random.randint(0, 100, 1000000)

# 低效的方式（使用循环）
import time
start = time.time()
result = []
for x in arr:
    if x > 50:
        result.append(x)
end = time.time()
print(f"循环方式耗时: {end - start:.4f}秒")

# 高效的方式（使用布尔索引）
start = time.time()
result = arr[arr > 50]
end = time.time()
print(f"布尔索引方式耗时: {end - start:.4f}秒")

# 使用np.where()进行条件赋值
arr = np.random.randint(0, 100, 10)
print("原始数组:", arr)
# 将所有大于50的值替换为100
arr = np.where(arr > 50, 100, arr)
print("替换后数组:", arr)




# 数据处理示例：筛选和排序考试成绩
# 创建考试成绩数组
scores = np.random.randint(0, 101, 100)

print("考试成绩统计:")
print(f"平均分: {np.mean(scores):.2f}")
print(f"最高分: {np.max(scores)}")
print(f"最低分: {np.min(scores)}")
print(f"及格率: {np.mean(scores >= 60) * 100:.2f}%")

# 筛选优秀学生（分数≥90）
excellent = scores[scores >= 90]
print(f"优秀学生人数: {len(excellent)}")
print(f"优秀学生分数: {np.sort(excellent)[::-1]}")

# 筛选需要补考的学生（分数<60）
need_retake = scores[scores < 60]
print(f"需要补考的学生人数: {len(need_retake)}")
print(f"需要补考的分数: {np.sort(need_retake)}")





import numpy.matlib

# 创建空矩阵
empty_matrix = np.matlib.empty((2, 3))
print("空矩阵:\n", empty_matrix)

# 创建零矩阵
zeros_matrix = np.matlib.zeros((2, 3))
print("零矩阵:\n", zeros_matrix)

# 创建单位矩阵
ones_matrix = np.matlib.ones((2, 3))
print("全1矩阵:\n", ones_matrix)

# 创建单位矩阵
identity_matrix = np.matlib.eye(3)
print("单位矩阵:\n", identity_matrix)

# 创建随机矩阵
random_matrix = np.matlib.rand(2, 3)
print("随机矩阵:\n", random_matrix)

# 创建对角矩阵
diag_matrix = np.matlib.diag([1, 2, 3])
print("对角矩阵:\n", diag_matrix)


# 从列表创建矩阵
matrix_from_list = np.matrix([[1, 2, 3], [4, 5, 6]])
print("从列表创建的矩阵:\n", matrix_from_list)

# 从字符串创建矩阵
matrix_from_string = np.matrix('1 2 3; 4 5 6')
print("从字符串创建的矩阵:\n", matrix_from_string)

# 从数组创建矩阵
array = np.array([[1, 2], [3, 4]])
matrix_from_array = np.matrix(array)
print("从数组创建的矩阵:\n", matrix_from_array)


# 创建示例矩阵
A = np.matrix([[1, 2], [3, 4]])
B = np.matrix([[5, 6], [7, 8]])

print("矩阵 A:\n", A)
print("矩阵 B:\n", B)

# 矩阵加法
print("A + B:\n", A + B)

# 矩阵减法
print("A - B:\n", A - B)

# 矩阵乘法（注意：与数组的逐元素乘法不同）
print("A * B:\n", A * B)

# 矩阵数乘
print("2 * A:\n", 2 * A)

# 矩阵转置
print("A 的转置:\n", A.T)

# 矩阵共轭转置
print("A 的共轭转置:\n", A.H)

# 矩阵求逆
A_inv = A.I
print("A 的逆矩阵:\n", A_inv)

# 验证逆矩阵
print("A * A_inv (应该接近单位矩阵):\n", A * A_inv)

# 矩阵行列式
det_A = np.linalg.det(A)
print("A 的行列式:", det_A)


# 特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
print("特征值:", eigenvalues)
print("特征向量:\n", eigenvectors)

# 奇异值分解
U, S, V = np.linalg.svd(A)
print("U 矩阵:\n", U)
print("奇异值:", S)
print("V 矩阵:\n", V)

# QR 分解
Q, R = np.linalg.qr(A)
print("Q 矩阵:\n", Q)
print("R 矩阵:\n", R)

# 矩阵属性
print("矩阵形状:", A.shape)
print("矩阵维度:", A.ndim)
print("矩阵大小:", A.size)
print("矩阵数据类型:", A.dtype)

# 矩阵方法
print("矩阵转置:\n", A.transpose())
print("矩阵共轭:\n", A.conjugate())
print("矩阵所有元素的和:", A.sum())
print("矩阵每列的和:", A.sum(axis=0))
print("矩阵每行的和:", A.sum(axis=1))

# 转换为数组
array_from_matrix = np.array(A)
print("从矩阵转换的数组:\n", array_from_matrix)


# 创建矩阵和数组
matrix = np.matrix([[1, 2], [3, 4]])
array = np.array([[1, 2], [3, 4]])

print("矩阵:\n", matrix)
print("数组:\n", array)

# 乘法运算的区别
print("矩阵乘法 (A * A):\n", matrix * matrix)
print("数组逐元素乘法 (A * A):\n", array * array)
print("数组矩阵乘法 (np.dot(A, A)):\n", np.dot(array, array))

# 幂运算的区别
print("矩阵的平方 (A**2):\n", matrix**2)  # 矩阵乘法
print("数组的平方 (A**2):\n", array**2)    # 逐元素平方

# 索引的区别
print("矩阵第一行:", matrix[0])  # 返回矩阵
print("数组第一行:", array[0])   # 返回一维数组

# 解线性方程组
# 方程组: 
# 1*x1 + 2*x2 = 5
# 3*x1 + 4*x2 = 6
A = np.matrix([[1, 2], [3, 4]])
b = np.matrix([[5], [6]])
x = np.linalg.solve(A, b)
print("方程组的解:\n", x)

# 验证解
print("验证: A * x =\n", A * x)

# 计算矩阵的秩
rank = np.linalg.matrix_rank(A)
print("矩阵的秩:", rank)

# 计算矩阵的迹
trace = np.trace(A)
print("矩阵的迹:", trace)

# 计算范数
norm = np.linalg.norm(A)
print("矩阵的范数:", norm)

# 创建特殊矩阵
# 范德蒙矩阵
vander_matrix = np.matlib.vander([1, 2, 3])
print("范德蒙矩阵:\n", vander_matrix)

# 托普利茨矩阵
toeplitz_matrix = np.matlib.toeplitz([1, 2, 3], [1, 4, 5])
print("托普利茨矩阵:\n", toeplitz_matrix)

# 循环矩阵
circulant_matrix = np.matlib.circulant([1, 2, 3])
print("循环矩阵:\n", circulant_matrix)

# 汉克尔矩阵
hankel_matrix = np.matlib.hankel([1, 2, 3], [3, 4, 5])
print("汉克尔矩阵:\n", hankel_matrix)

# 创建示例矩阵
A = np.matrix([[1, 2], [3, 4]])
B = np.matrix([[5, 6], [7, 8]])

# 水平拼接
horizontal_stack = np.hstack((A, B))
print("水平拼接:\n", horizontal_stack)

# 垂直拼接
vertical_stack = np.vstack((A, B))
print("垂直拼接:\n", vertical_stack)

# 矩阵分割
# 水平分割
split_horizontal = np.hsplit(horizontal_stack, 2)
print("水平分割结果:")
for i, part in enumerate(split_horizontal):
    print(f"部分 {i+1}:\n", part)

# 垂直分割
split_vertical = np.vsplit(vertical_stack, 2)
print("垂直分割结果:")
for i, part in enumerate(split_vertical):
    print(f"部分 {i+1}:\n", part)

# 线性回归示例
# 假设我们有数据点 (1, 1), (2, 2), (3, 2), (4, 3)
# 我们想拟合一个线性模型 y = β0 + β1*x

# 创建设计矩阵 X 和响应向量 y
X = np.matrix([[1, 1], [1, 2], [1, 3], [1, 4]])
y = np.matrix([[1], [2], [2], [3]])

# 计算回归系数 β = (X^T X)^(-1) X^T y
X_T = X.T
X_T_X = X_T * X
X_T_X_inv = X_T_X.I
beta = X_T_X_inv * X_T * y

print("回归系数:")
print("β0 =", beta[0, 0])
print("β1 =", beta[1, 0])

# 预测
x_new = 5
y_pred = beta[0, 0] + beta[1, 0] * x_new
print(f"当 x = {x_new} 时，预测 y = {y_pred}")


import time

# 比较矩阵和数组的性能
size = 1000

# 创建大型矩阵和数组
matrix_large = np.matlib.rand(size, size)
array_large = np.random.rand(size, size)

# 矩阵乘法性能
start = time.time()
result_matrix = matrix_large * matrix_large
end = time.time()
print(f"矩阵乘法耗时: {end - start:.4f}秒")

# 数组矩阵乘法性能
start = time.time()
result_array = np.dot(array_large, array_large)
end = time.time()
print(f"数组矩阵乘法耗时: {end - start:.4f}秒")

# 在现代NumPy中，通常推荐使用数组而不是矩阵
# 因为数组更通用，性能更好，并且有更多的函数支持


# 创建示例矩阵
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

print("矩阵 A:\n", A)
print("矩阵 B:\n", B)

# 矩阵乘法
print("矩阵乘法 A @ B:\n", A @ B)
print("矩阵乘法 np.matmul(A, B):\n", np.matmul(A, B))
print("点积 np.dot(A, B):\n", np.dot(A, B))

# 向量点积
v1 = np.array([1, 2, 3])
v2 = np.array([4, 5, 6])
print("向量点积:", np.dot(v1, v2))

# 外积
print("外积:\n", np.outer(v1, v2))

# 张量积
print("张量积:\n", np.kron(A, B))

# 矩阵转置
print("A 的转置:\n", A.T)

# 矩阵共轭转置
C = np.array([[1+2j, 3+4j], [5+6j, 7+8j]])
print("复数矩阵 C:\n", C)
print("C 的共轭转置:\n", C.conj().T)
print("使用 np.matrix.H:\n", np.matrix(C).H)


# 特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
print("特征值:", eigenvalues)
print("特征向量:\n", eigenvectors)

# 验证特征分解: A * v = λ * v
for i in range(len(eigenvalues)):
    print(f"验证特征值 {eigenvalues[i]}:\n", A @ eigenvectors[:, i] - eigenvalues[i] * eigenvectors[:, i])

# 对于对称/厄米特矩阵
A_sym = np.array([[2, 1], [1, 2]])
eigenvalues_sym, eigenvectors_sym = np.linalg.eigh(A_sym)
print("对称矩阵的特征值:", eigenvalues_sym)
print("对称矩阵的特征向量:\n", eigenvectors_sym)

# 奇异值分解
U, S, Vh = np.linalg.svd(A)
print("左奇异向量 U:\n", U)
print("奇异值 S:", S)
print("右奇异向量 Vh:\n", Vh)

# 验证 SVD: A = U * diag(S) * Vh
Sigma = np.zeros((2, 2))
np.fill_diagonal(Sigma, S)
print("验证 SVD:\n", U @ Sigma @ Vh)

# 经济型 SVD
U_econ, S_econ, Vh_econ = np.linalg.svd(A, full_matrices=False)
print("经济型 SVD 的 U:\n", U_econ)
print("经济型 SVD 的 S:", S_econ)
print("经济型 SVD 的 Vh:\n", Vh_econ)


# QR 分解
Q, R = np.linalg.qr(A)
print("正交矩阵 Q:\n", Q)
print("上三角矩阵 R:\n", R)

# 验证 QR 分解: A = Q * R
print("验证 QR 分解:\n", Q @ R)

# 验证 Q 的正交性: Q^T * Q = I
print("验证 Q 的正交性:\n", Q.T @ Q)

# Cholesky 分解（用于对称正定矩阵）
A_pos_def = np.array([[4, 12, -16], [12, 37, -43], [-16, -43, 98]])
L = np.linalg.cholesky(A_pos_def)
print("Cholesky 下三角矩阵 L:\n", L)
print("验证 Cholesky 分解:\n", L @ L.T)

# LU 分解
P, L, U = np.linalg.lu(A)
print("置换矩阵 P:\n", P)
print("下三角矩阵 L:\n", L)
print("上三角矩阵 U:\n", U)

# 验证 LU 分解: P * A = L * U
print("验证 LU 分解:\n", P @ A - L @ U)


# 矩阵求逆
A_inv = np.linalg.inv(A)
print("A 的逆矩阵:\n", A_inv)
print("验证逆矩阵: A * A_inv =\n", A @ A_inv)

# 伪逆矩阵（Moore-Penrose 伪逆）
A_pinv = np.linalg.pinv(A)
print("A 的伪逆矩阵:\n", A_pinv)

# 矩阵行列式
det_A = np.linalg.det(A)
print("A 的行列式:", det_A)

# 矩阵的迹
trace_A = np.trace(A)
print("A 的迹:", trace_A)




# 解线性方程组 Ax = b
b = np.array([5, 6])
x = np.linalg.solve(A, b)
print("线性方程组的解 x:", x)
print("验证解: A * x =\n", A @ x)

# 最小二乘解（对于超定系统）
A_over = np.array([[1, 1], [1, 2], [1, 3]])
b_over = np.array([1, 2, 2])
x_lstsq = np.linalg.lstsq(A_over, b_over, rcond=None)[0]
print("最小二乘解:", x_lstsq)
print("残差:", np.linalg.lstsq(A_over, b_over, rcond=None)[1])

# 使用伪逆求解
x_pinv = np.linalg.pinv(A_over) @ b_over
print("使用伪逆求解:", x_pinv)


# 矩阵范数
print("Frobenius 范数:", np.linalg.norm(A, 'fro'))
print("1-范数（列和范数）:", np.linalg.norm(A, 1))
print("2-范数（谱范数）:", np.linalg.norm(A, 2))
print("无穷范数（行和范数）:", np.linalg.norm(A, np.inf))

# 向量范数
v = np.array([1, 2, 3])
print("向量 2-范数:", np.linalg.norm(v))
print("向量 1-范数:", np.linalg.norm(v, 1))
print("向量无穷范数:", np.linalg.norm(v, np.inf))

# 条件数
print("矩阵条件数 (2-范数):", np.linalg.cond(A))
print("矩阵条件数 (Frobenius 范数):", np.linalg.cond(A, 'fro'))

# 矩阵指数
print("矩阵指数:\n", np.linalg.matrix_exp(A))

# 矩阵对数
A_log = np.linalg.matrix_log(np.linalg.matrix_exp(A))
print("矩阵对数:\n", A_log)

# 矩阵幂
print("矩阵平方:\n", np.linalg.matrix_power(A, 2))
print("矩阵逆:\n", np.linalg.matrix_power(A, -1))


# 求解 Sylvester 方程: AX + XB = C
B_syl = np.array([[5, 6], [7, 8]])
C_syl = np.array([[9, 10], [11, 12]])
X_syl = np.linalg.solve_sylvester(A, B_syl, C_syl)
print("Sylvester 方程的解:\n", X_syl)
print("验证: A*X + X*B =\n", A @ X_syl + X_syl @ B_syl)

# 求解连续 Lyapunov 方程: AX + XA^H = Q
Q_lyap = np.array([[1, 0], [0, 1]])
X_lyap = np.linalg.solve_continuous_lyapunov(A, Q_lyap)
print("Lyapunov 方程的解:\n", X_lyap)
print("验证: A*X + X*A^H =\n", A @ X_lyap + X_lyap @ A.conj().T)

# 使用 SVD 实现 PCA
def pca(X, n_components=2):
    # 中心化数据
    X_centered = X - np.mean(X, axis=0)
    
    # 计算 SVD
    U, S, Vh = np.linalg.svd(X_centered, full_matrices=False)
    
    # 选择前 n_components 个主成分
    components = Vh[:n_components]
    
    # 投影数据
    projected = X_centered @ components.T
    
    return projected, components, S

# 示例数据
np.random.seed(42)
X = np.random.randn(100, 3)  # 100 个样本，3 个特征

# 应用 PCA
projected, components, singular_values = pca(X, n_components=2)
print("投影后的数据形状:", projected.shape)
print("主成分:\n", components)
print("奇异值:", singular_values)

# 使用线性代数实现线性回归
def linear_regression(X, y):
    # 添加偏置项
    X_with_bias = np.c_[np.ones(X.shape[0]), X]
    
    # 计算参数: θ = (X^T X)^(-1) X^T y
    theta = np.linalg.inv(X_with_bias.T @ X_with_bias) @ X_with_bias.T @ y
    
    return theta

# 示例数据
X = np.array([[1], [2], [3], [4]])
y = np.array([1, 2, 2, 3])

# 拟合模型
theta = linear_regression(X, y)
print("回归系数:", theta)

# 预测
X_new = np.array([[5], [6]])
X_new_with_bias = np.c_[np.ones(X_new.shape[0]), X_new]
y_pred = X_new_with_bias @ theta
print("预测值:", y_pred)






# 使用更高效的函数
# 对于对称矩阵，使用 eigh 而不是 eig
A_sym = np.array([[2, 1], [1, 2]])
eigenvalues, eigenvectors = np.linalg.eigh(A_sym)  # 比 eig 更快更稳定

# 使用 solve 而不是 inv 来求解线性系统
# 不推荐: x = np.linalg.inv(A) @ b
# 推荐: x = np.linalg.solve(A, b)  # 更数值稳定且高效

# 处理奇异矩阵或病态矩阵
try:
    x = np.linalg.solve(A, b)
except np.linalg.LinAlgError:
    print("矩阵是奇异的，使用最小二乘解")
    x = np.linalg.lstsq(A, b, rcond=None)[0]

# 检查矩阵条件数
cond_number = np.linalg.cond(A)
if cond_number > 1e10:
    print("警告: 矩阵是病态的，条件数为", cond_number)